//
//  ViewController.swift
//  SwiftLearning
//
//  Created by 黄龙 on 2023/11/21.
//

import UIKit

//登录框状态枚举
enum LoginShowType {
    case NONE
    case USER
    case PASS
}

//一个简单的登录窗口，作为首页
class ViewController: UIViewController {
    var isAppeared:Bool = false
    var imgLeftHand:UIImageView?
    var imgRightHand:UIImageView?
    var imgLeftMaskHand:UIImageView?
    var imgRightMaskHand:UIImageView?
    var loginBtn: UIButton?
    var circleLayer:CAShapeLayer?
    
    var tmpRoundLayer: CAShapeLayer?
    var dragLabel:UILabel?
    var animateType = 0
    
    //登录框状态
    var showType:LoginShowType = LoginShowType.NONE
    
    deinit {
        print("~deinit：ViewController")
    }
    
    func preInitView(){
        self.view.backgroundColor = .defaultBackgroundColor
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        initView()
    }
    
    override func viewDidAppear(_ animated:Bool){
        super.viewDidAppear(animated)
        if isAppeared{
//注销后回到本页面，登录按钮复原:
            if let circleLayer = circleLayer{
                circleLayer.removeAllAnimations()
                circleLayer.removeFromSuperlayer()
            }
            UIView.animate(withDuration: 0.5, delay: 0) {[weak self] in
                if let self = self{
                    self.loginBtn!.frame = CGRect(x: 30.wFit, y: screen_H/2, width: screen_W-60.wFit, height: 44.wFit)
                }
            } completion: {[weak self] _ in
                if let self = self{
                    self.loginBtn?.setTitle("账号登录", for: .normal)
                }
            }
        }
        
        if let snapshot = self.view.viewWithTag(999) as? UIImageView{
//present页面关闭时，显示破碎玻璃效果
            
//方法一：
            if (0 == animateType){
                let starsCrush = StarsViewGLAnimator()
                starsCrush.duration = 1.25
                starsCrush.xSmallDiff = -50.0
                starsCrush.xBigDiff = 50.0
                starsCrush.animateCrushView(crushView: snapshot, In: snapshot.superview!)
                animateType = 1
            }else{
                //方法2:
                //            snapshot.animateToCrush(crushSize: CGSize(width: 50, height: 50),xSmall: -15.0,xBig: 15.0, duration: 0.75) //此方法有缺陷
                snapshot.animateImageToCrush(crushSize: CGSize(width: 10, height: 10),xSmall: -10.0,xBig: 10.0, duration: 1.25)
                animateType = 0
            }
            if let _ = snapshot.superview{
                snapshot.removeFromSuperview()
            }

        }
        
        isAppeared = true
    }
    
    func initView(){
        //猫头鹰头部
        let iHeight = 108.0
        let iWidth = 211.0
        let imgOwlHead =  UIImageView(frame: CGRect(x: screen_W/2-iWidth.wFit/2, y: iHeight.hFit, width: iWidth.wFit, height: iHeight.wFit))
        imgOwlHead.imageWithUrl("login-owl-head") //211*108
        imgOwlHead.layer.masksToBounds = true
        self.view.addSubview(imgOwlHead)
        
        //登录框背景CGRectMake(15, 200, mainSize.width - 30, 160)
        let vLogin =  UIView(frame:CGRect(x: 15.wFit, y: imgOwlHead.frame.maxY-9.wFit, width: screen_W - 30.wFit, height: 160.wFit))
        vLogin.layer.borderWidth = 0.5
        vLogin.layer.borderColor = UIColor.lightGray.cgColor // UIColor.lightGrayColor().CGColor
        vLogin.backgroundColor = .systemGroupedBackground //用系统背景，则是会自适应黑暗模式
        vLogin.layer.cornerRadius = 15.0
        self.view.insertSubview(vLogin, belowSubview: imgOwlHead)
        
        //猫头鹰左手(遮眼睛的)
        let handW = 40.wFit
        let handH = 65.wFit
        let rectLeftHand = CGRect(x: 0, y: imgOwlHead.bounds.height - 15.wFit, width: handW, height: handH)
        imgLeftHand = UIImageView(frame:rectLeftHand)
        if let imgHand = imgLeftHand{
            imgHand.image = UIImage(named:"login-owl-arm-left")
            imgOwlHead.addSubview(imgHand)
        }
        
        //猫头鹰右手(遮眼睛的)
        let rectRightHand = CGRect(x: imgOwlHead.bounds.width - handW, y: imgOwlHead.bounds.height-15.wFit, width: handW, height: handH)
        imgRightHand = UIImageView(frame:rectRightHand)
        if let imgHand = imgRightHand{
            imgHand.image = UIImage(named:"login-owl-arm-right")
            imgOwlHead.addSubview(imgHand)
        }
        
        
        //猫头鹰左手(圆形的)
        let maskHandW = 40.wFit
        let rectLeftHandGone = CGRect(x: imgOwlHead.frame.minX, y: imgOwlHead.frame.maxY-26.wFit, width: maskHandW, height: maskHandW)
        imgLeftMaskHand = UIImageView(frame:rectLeftHandGone)
        if let maskHand = imgLeftMaskHand{
            maskHand.image = UIImage(named:"icon_hand")
            self.view.addSubview(maskHand)
        }
        //猫头鹰右手(圆形的)
        let rectRightHandGone = CGRect(x: imgOwlHead.frame.maxX-maskHandW, y: imgOwlHead.frame.maxY-26.wFit , width: maskHandW, height: maskHandW)
        imgRightMaskHand = UIImageView(frame:rectRightHandGone)
        if let maskHand = imgRightMaskHand{
            maskHand.image = UIImage(named:"icon_hand")
            self.view.addSubview(maskHand)
        }
        
        //用户名输入框CGRectMake(30, 30, vLogin.frame.size.width - 60, 44)
        let txtUser = UITextField(frame:CGRect(x: 30.wFit, y: 30.wFit, width: vLogin.frame.width - 60.wFit, height: 44.wFit))
        txtUser.delegate = self
        txtUser.layer.cornerRadius = 5
        txtUser.layer.borderColor = UIColor.lightGray.cgColor
        txtUser.layer.borderWidth = 0.5
        txtUser.leftView = UIView(frame:CGRect(x: 0, y: 0, width: 44.wFit, height: 44.wFit))
        txtUser.leftViewMode = UITextField.ViewMode.always
        txtUser.keyboardType = UIKeyboardType.emailAddress
        txtUser.returnKeyType = UIReturnKeyType.next
        txtUser.tag = 100
        //用户名输入框左侧图标
        let imgUser =  UIImageView(frame:CGRect(x: 11.wFit, y: 11.wFit, width: 22.wFit, height: 22.wFit))
        imgUser.image = UIImage(named:"login-userico")
        txtUser.leftView!.addSubview(imgUser)
        vLogin.addSubview(txtUser)
        //给输入框键盘添加toolbar及完成按钮
        let toolbar:UIToolbar = UIToolbar(frame: CGRect(x: 0, y: 0,   width: screen_W, height: 30.wFit))
        let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let doneBtn: UIBarButtonItem = UIBarButtonItem(title: "完成", style: .done, target: self, action: #selector(doneButtonAction))
        toolbar.setItems([flexSpace, doneBtn], animated: false)
        toolbar.sizeToFit()
        //对输入框进行设置
        txtUser.inputAccessoryView = toolbar
        
        //密码输入框
        let txtPwd = UITextField(frame:CGRect(x: 30.wFit, y: 90.wFit, width: vLogin.frame.width - 60.wFit, height: 44.wFit))
        txtPwd.delegate = self
        txtPwd.layer.cornerRadius = 5
        txtPwd.layer.borderColor = UIColor.lightGray.cgColor
        txtPwd.layer.borderWidth = 0.5
        txtPwd.isSecureTextEntry = true
        txtPwd.leftView = UIView(frame:CGRect(x: 0, y: 0, width: 44.wFit, height: 44.wFit))
        txtPwd.leftViewMode = UITextField.ViewMode.always
        txtPwd.keyboardType = UIKeyboardType.default
        txtPwd.returnKeyType = UIReturnKeyType.done
        txtPwd.tag = 101
        //密码输入框左侧图标
        let imgPwd =  UIImageView(frame:CGRect(x: 11.wFit, y: 11.wFit, width: 22.wFit, height: 22.wFit))
        imgPwd.image = UIImage(named:"login-passwordico")
        txtPwd.leftView!.addSubview(imgPwd)
        vLogin.addSubview(txtPwd)
        
        loginBtn = UIButton(frame: CGRect(x: 30.wFit, y: screen_H/2, width: screen_W-60.wFit, height: 44.wFit))
        if let button = loginBtn{
            self.view.addSubview(button)
            button.layer.borderColor = UIColor.systemBrown.cgColor
            button.layer.borderWidth = 1.0
            button.layer.cornerRadius = 22.wFit
            button.setTitle("账号登录", for: .normal)
            button.setTitleColor(.label, for: .normal)
            button.addActionWithBlock { [weak self] sender in
                if let self = self{
                    sender.setTitle("‑", for: .normal)
                    UIView.animate(withDuration: 0.5, delay: 0) {
                        sender.frame = CGRect(x: screen_W/2 - 22.wFit, y: screen_H/2, width: 44.wFit, height: 44.wFit)
                    } completion: { _ in
                        sender.layer.borderColor = UIColor.lightGray.cgColor
                        let dotLayer = UIView()
                        sender.addSubview(dotLayer)
                        dotLayer.frame = CGRect(x: 44.wFit/2-10, y: 44.wFit/2-1, width: 20, height: 2)
                        dotLayer.backgroundColor = .label
                        sender.setTitle("", for: .normal)
                        UIView.animate(withDuration: 0.25, delay: 0.25) {
                            dotLayer.frame = CGRect(x: 44.wFit/2-1, y: 44.wFit/2-1, width: 2, height: 2)
                        } completion: { _ in
                            UIView.animate(withDuration: 0.25, delay: 0.25) {
                                dotLayer.frame = CGRect(x: 44.wFit - 2, y: 44.wFit/2-1, width: 2, height: 2)
                            } completion: { _ in
                                dotLayer.removeFromSuperview()
                                let aniView = CircleLineLoadingView(frame: CGRect(x: 0, y: 0, width: 44.wFit, height: 44.wFit))
                                sender.addSubview(aniView)
                                aniView.tag = 200
                                aniView.updateStrokeColor(.label)
                                aniView.startAnimate()
                                self.perform(#selector(self.delayToLoginOK), with: nil, afterDelay: 4*2.0)
                            }
                        }
                        
                    }
                    
                }
            }
        }
        
        
        let dragView = UIView(frame: CGRect(x: 30.wFit, y: screen_H/2+100.hFit, width: screen_W-60.wFit, height: 80.wFit))
        self.view.addSubview(dragView)
        dragView.layer.cornerRadius = 5
        dragView.layer.borderWidth = 0.5
        dragView.layer.borderColor = UIColor.lightGray.cgColor
        dragView.tag = 300
        dragLabel = UILabel(frame: CGRect(x: 15, y: 20, width: dragView.bounds.width-30, height: 40))
        if let dragLabel = dragLabel{
            dragView.addSubview(dragLabel)
            dragLabel.textAlignment = .right
            dragLabel.text = "向右滑动验证登录>>"
            dragLabel.textColor = .label
            dragLabel.font = .systemFont(ofSize: 20)
        }

        let roundW = dragView.bounds.height - 20
        tmpRoundLayer = dragView.addDashdeBorderLayer(lineFrame: CGRect(x: 10, y: 10, width: roundW, height: roundW), color: .lightGray, lineWidth: 1,cornerRadius: 10)
        
        let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swipeToRight(_:)))
        swipeRight.direction = .right
        dragView.addGestureRecognizer(swipeRight)
        
        let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(swipeToLeft(_:)))
        swipeLeft.direction = .left
        dragView.addGestureRecognizer(swipeLeft)
    }
    
    @objc func swipeToRight(_ recognizer:UISwipeGestureRecognizer){
        print("swipeToRight")
        if let dragView = self.view.viewWithTag(300){
            let lineColor = UIColor(red: 250.0/255.0, green: 216.0/255.0, blue: 115.0/255.0, alpha: 1.0).cgColor
            let roundW = dragView.bounds.height - 20
            let path = UIBezierPath(roundedRect: CGRect(x: 10, y: 10, width: roundW, height: roundW), cornerRadius: 10)
//注意：矩形的线条起始点为坐标(0,0)处，而圆角矩形的起点坐标为(radius,0)处，且其线条行进路线为顺时针方向
//所以怎么让线条动画，从右侧中间点开始顺时针行走，走一整圈后从右侧中间点向右滑出呢？
            let roundLayer = CAShapeLayer()
            roundLayer.position = CGPoint(x: 0, y: 0)
            roundLayer.path = path.cgPath
            roundLayer.fillColor = UIColor.clear.cgColor
            roundLayer.strokeColor = lineColor
            roundLayer.lineCap = CAShapeLayerLineCap.round
            roundLayer.lineWidth = 4;
            dragView.layer.addSublayer(roundLayer)
            let strokeEnd = CABasicAnimation(keyPath: "strokeEnd")
            strokeEnd.fromValue = 0
            strokeEnd.toValue = 1.0
            strokeEnd.duration = 0.8
            strokeEnd.timingFunction = CAMediaTimingFunction(name: .easeIn)
            strokeEnd.fillMode = .forwards
            strokeEnd.isRemovedOnCompletion = false
            roundLayer.strokeStart = 2.5/8.0 //指示动画的起始点在1个单位path中哪处相对位置,
            roundLayer.add(strokeEnd, forKey: "strokeEnd")
            //但结束位置始终是在(radius,0)改不了，咋破？设置strokeEnd = 1+2.7/8.0肯定是无效的，已经超出1个单位
            //于是想到一个方法,在(radius,0)处结束时接着再画一个圆角矩形，而其起点为0，终点直接设置strokeEnd=2.7/8.0不就可以了么
            let currentTime = CACurrentMediaTime()
            let continueLayer = CAShapeLayer()
            continueLayer.position = CGPoint(x: 0, y: 0)
            continueLayer.path = path.cgPath
            continueLayer.fillColor = UIColor.clear.cgColor
            continueLayer.strokeColor = lineColor
            continueLayer.lineCap = CAShapeLayerLineCap.round
            continueLayer.lineWidth = 4;
            dragView.layer.addSublayer(continueLayer)
            let strokeEnd_continue = CABasicAnimation(keyPath: "strokeEnd")
            strokeEnd_continue.fromValue = 0
            strokeEnd_continue.toValue = 2.5/8.0 //path的总长度是1个单位，但本动画不需要绘制1个单位总长度，否则会走完1整个单位，然后回缩到continueLayer.strokeEnd处
            strokeEnd_continue.duration = 0.25 //约为0.8*2.5/8s
            strokeEnd_continue.timingFunction = CAMediaTimingFunction(name: .easeOut)
            strokeEnd_continue.beginTime =  currentTime + 0.8
            strokeEnd_continue.fillMode = .backwards //很重要，切记
            continueLayer.strokeEnd = 2.5/8.0
            continueLayer.add(strokeEnd_continue, forKey: "strokeEnd_continue")
            //在roundLayer线条结束后，确实可以继续往前走，走到2.6/8.0处，但是这段后走的线路会先直接显示出来，什么鬼？不是设置了beginTime延后2秒执行么？
            //注意，这是因为dragView.layer.addSublayer(continueLayer)添加到layer，当然就即时显示出来了，要想它在动画开始之后显示，
            //需要设置strokeEnd_continue.fillMode = .backwards，在动画开始前，将动画加入了一个layer，layer便会立即进入动画的初始状态并等待动画开始，这样就OK了，哈哈！
            //那为什么strokeEnd没有设置fillMode为backwards，却不会先显示整个roundLayer，然后再显示线条动画呢，
            //因为dragView.layer.addSublayer(roundLayer)添加完了之后,就立即开始动画了，而strokeEnd_continue却是延时开始的动画

//右出线条，从矩形线条结束处，向右出一个线条，造成一个矩形线向右飞出的效果
            let linePath = UIBezierPath()
            linePath.move(to: CGPoint(x: 10+roundW, y: 10+roundW/2-2))
            linePath.addLine(to: CGPoint(x: dragView.bounds.width - 20 , y: 10+roundW/2))
            let lineLayer = CAShapeLayer()
            lineLayer.path = linePath.cgPath
            lineLayer.fillColor = UIColor.clear.cgColor
            lineLayer.strokeColor = lineColor
            lineLayer.lineCap = CAShapeLayerLineCap.round
            lineLayer.lineWidth = 4;
            dragView.layer.addSublayer(lineLayer)
            let strokeEnd_line = CABasicAnimation(keyPath: "strokeEnd")
            strokeEnd_line.fromValue = 0
            strokeEnd_line.toValue = 1
            strokeEnd_line.duration = 1.0
            strokeEnd_line.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
            strokeEnd_line.beginTime =  currentTime + 0.8 + 0.25
            strokeEnd_line.fillMode = .backwards
            lineLayer.add(strokeEnd_line, forKey: "strokeEnd_line")

//线条向右滑时，开始顺时针清除矩形线条，达到一种矩形线条向右飞出的动画
            //先将第一段绘制的矩形线条回收
            let strokeStart_round_1 = CABasicAnimation(keyPath: "strokeStart")
            strokeStart_round_1.fromValue =  2.5/8.0
            strokeStart_round_1.toValue = 1.0
            strokeStart_round_1.duration = 0.8
            strokeStart_round_1.beginTime =  currentTime + 0.75 //即将绘制第2段round前就开始回收
            strokeStart_round_1.fillMode = .forwards
            strokeStart_round_1.isRemovedOnCompletion = false
            strokeStart_round_1.timingFunction = CAMediaTimingFunction(name: .linear)
            roundLayer.add(strokeStart_round_1, forKey: "strokeStart_round_1")
            //接着回收第2段矩形线条
            let strokeStart_round_2 = CABasicAnimation(keyPath: "strokeStart")
            strokeStart_round_2.fromValue = 0
            strokeStart_round_2.toValue = 2.6/8.0
            strokeStart_round_2.duration =  0.2
            strokeStart_round_2.beginTime =  currentTime + 0.75 + 0.8 //绘制第2段round时就开始回收
            strokeStart_round_2.fillMode = .forwards
            strokeStart_round_2.isRemovedOnCompletion = false
            strokeStart_round_2.timingFunction = CAMediaTimingFunction(name: .linear)
            continueLayer.add(strokeStart_round_2, forKey: "strokeStart_round_2")
            //最后再回收一点飞出的横线条
            let strokeStart_line = CABasicAnimation(keyPath: "strokeStart")
            strokeStart_line.fromValue = 0
            strokeStart_line.toValue = 0.1
            strokeStart_line.duration = 0.15
            strokeStart_line.beginTime =  currentTime + 0.75 + 0.8 + 0.2 //横线绘制完毕时回收前端部分
            strokeStart_line.fillMode = .forwards
            strokeStart_line.isRemovedOnCompletion = false
            strokeStart_line.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
            lineLayer.add(strokeStart_line, forKey: "strokeStart_line")

//线条即将结束前，显示打勾动画
            let gouPath = UIBezierPath()
            gouPath.move(to: CGPoint(x: 10+15, y: roundW*0.7))
            gouPath.addLine(to: CGPoint(x: roundW/2+5, y: roundW-5))
            gouPath.addLine(to: CGPoint(x: roundW-5, y: 10+20))
            let strokeEnd_gou = CABasicAnimation(keyPath: "strokeEnd")
            strokeEnd_gou.fromValue = 0
            strokeEnd_gou.toValue = 1
            strokeEnd_gou.duration = 0.5
            strokeEnd_gou.beginTime = currentTime + 0.75 + 0.8 + 0.2
            strokeEnd_gou.fillMode = .backwards
            let gouLayer = CAShapeLayer()
            gouLayer.path = gouPath.cgPath
            gouLayer.fillColor = UIColor.clear.cgColor
            gouLayer.strokeColor = lineColor
            gouLayer.lineCap = CAShapeLayerLineCap.round
            gouLayer.lineJoin = .round //打勾地方圆滑处理
            gouLayer.lineWidth = 4;
            dragView.layer.addSublayer(gouLayer)
            gouLayer.add(strokeEnd_gou, forKey: "strokeEnd_gou")
//打勾的同时，显示旋转+放大虚线动画
            let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")
            scaleAnimation.fromValue = 0
            scaleAnimation.toValue = 1.0
            scaleAnimation.duration = 0.35
            let roateAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
            roateAnimation.fromValue = 0
            roateAnimation.toValue = 2*Double.pi
            
            let scaleRoateGroup = CAAnimationGroup()
            scaleRoateGroup.beginTime = currentTime + 1.0 + 0.8
            scaleRoateGroup.duration = 0.75
            scaleRoateGroup.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
            scaleRoateGroup.fillMode = .backwards
            //非Stroke动画，即使设置了backwards，只要beginTime有延时，仍旧会在addSublayer后会显示出来,只好把scale的fromeValue设置成0不可见了
//当然也可以在strokeEnd_gou动画结束后事件中确发scale即时动画来解决
            scaleRoateGroup.animations = [scaleAnimation,roateAnimation]
            let scaleLayer = dragView.addDashdeBorderLayer(lineFrame: CGRect(x: 10, y: 10, width: roundW, height: roundW), color: .yellow, lineWidth: 4,lineDashPattern: [4,12],cornerRadius: 10)
            scaleLayer.add(scaleRoateGroup, forKey: "scaleRoateGroup")
            
            self.perform(#selector(removeTempRoundLayer), with: nil, afterDelay: 1.8)
        }
    }
    
    @objc func removeTempRoundLayer(){
        tmpRoundLayer?.removeFromSuperlayer()
        if let dragLabel = dragLabel{
            dragLabel.text = "<<向左滑动重置验证 "
        }
        self.perform(#selector(showMainVC(_:)), with: "1", afterDelay: 1.0)
    }
    
    @objc func delayToLoginOK(){
        if let button = loginBtn{
            if let aniCircle = button.viewWithTag(200) as? CircleLineLoadingView{
                aniCircle.stopAnimation()
                aniCircle.removeFromSuperview()
//在里面打勾,然后跳到主UI
//MARK: - 弧形线条及打勾动画
//勾的路径
                let path = UIBezierPath()
//先逆时针圆弧
                let startAngle:CGFloat = CGFloat(1/3 * Double.pi) //60度
                let endAngle:CGFloat = CGFloat(19/18 * Double.pi)  //190度
                path.addArc(withCenter: CGPoint(x: button.frame.size.width/2.0, y: button.frame.size.height/2.0), radius: button.frame.size.width/2.0, startAngle: startAngle, endAngle: endAngle, clockwise: false)
//逆时针绘制60度到190度的弧线
//UIBezierPath.addArc方法，绘制弧线，其度数是右水平3点钟方向为0度，然顺时针方向数度数，故60度是右下5点钟的位置，180度是左水平线9点钟方向，190度是左水平线再往上走10度,
//然后因为clockwise=false，是逆时针绘制，所绘制的弧线，是从右下60度的位置逆时针向上然往左到190度位置的一段弧线，是大半个圆的弧线
//如果改成clockwise=true，顺时针绘制，则是是从右下60度的位置顺时针向下再往左到190度位置的一段弧线，是一小段弧线
//clockwise是弧线绘制的线路前进的方向，不是数度数的方向(刚开始用的时候老是混淆为数度数的方向)
//数度数方向默认是顺时针方向(度数为负数时才为逆时针方向)（即默认右水平3点钟方向为0度，正下方6点钟为90度，左水平9点钟方向为180度，正上方12点为270度或-90度）
//所以如果起点是60度，终点是40度，则clockwise=true顺时钟绘制，则弧线几乎是整个圆，而clockwise=false逆时绘制，则只有一小段弧钱
                
                path.addLine(to: CGPoint(x: 44.wFit/2-3.wFit ,y: 44.wFit - 8.wFit)) //勾的底点
//会从190度位置(大概9点半的位置)连一条线到勾的底部点
                path.addLine(to: CGPoint(x: 44.wFit - 5.wFit, y: 5.wFit)) //勾的末点
//勾的右半部分
                circleLayer = CAShapeLayer()
                if let circleLayer = circleLayer{
                    circleLayer.position = CGPoint(x: 0, y: 0)
                    circleLayer.path = path.cgPath
                    circleLayer.fillColor = UIColor.clear.cgColor
                    circleLayer.strokeColor = UIColor(red: 150.0/255.0, green: 216.0/255.0, blue: 115.0/255.0, alpha: 1.0).cgColor
                    circleLayer.lineCap = CAShapeLayerLineCap.round
                    circleLayer.lineWidth = 4;
                    circleLayer.lineJoin = .round //打勾地方圆滑处理
                    button.layer.addSublayer(circleLayer)
                    //到此circleLayer画出了弧形线条和勾线条(如果没有下面的stroke动画，会发现勾很难看，因为勾的起始位置在190度处太高)
                    
                    let factor = 0.045
                    let timing = CAMediaTimingFunction(controlPoints: 0.3, 0.6, 0.8, 1.2)
                    
                    let strokeEnd = CABasicAnimation(keyPath: "strokeEnd")
                    strokeEnd.fromValue = 0
                    strokeEnd.toValue = 1.0 //其实应该设置成0.93，因为不需绘制完1整个Path单位，但设置成1个单位，会有让“勾”有一个回缩的抖动动画效果感觉更好
                    strokeEnd.duration = 10.0*factor
                    strokeEnd.timingFunction = timing
                    strokeEnd.delegate = self
                    circleLayer.strokeEnd = 0.93 //将终点定在全部形条的93%处，于是会导致勾的右侧线条末尾会截短一部分
                    circleLayer.add(strokeEnd, forKey: "strokeEnd")
                    ////利用strokeEnd动画，从起始处0开始慢慢沿着path显示出线条，线条会先显示完整，然后回到strokeEnd = 0.93处
                    
                    let strokeStart = CABasicAnimation(keyPath: "strokeStart")
                    strokeStart.fromValue = 0
                    strokeStart.toValue = 0.68
                    strokeStart.duration =  7.0*factor
                    strokeStart.beginTime =  CACurrentMediaTime() + 3.0*factor
                    strokeStart.fillMode = CAMediaTimingFillMode.backwards
                    //kCAFillModeRemoved 这个是默认值，也就是说当动画开始前和动画结束后，动画对layer都没有影响，动画结束后，layer会恢复到之前的状态
                    //kCAFillModeForwards 当动画结束后，layer会一直保持着动画最后的状态(和removedOnCompletion = false联用)
                    //kCAFillModeBackwards 在动画开始前，只需要将动画加入了一个layer，layer便立即进入动画的初始状态并等待动画开始。
                    //kCAFillModeBoth这个其实就是上面两个的合成.动画加入后开始之前，layer便处于动画初始状态，动画结束后layer保持动画最后的状态
                    strokeStart.timingFunction = timing
                    circleLayer.strokeStart = 0.68
                    circleLayer.add(strokeStart, forKey: "strokeStart")
                    //利用strokeStart动画，将线条从起始处0，慢慢沿着path进行抹除, strokeStart = 0.68 设置只清除到整个线条的68%处为止，刚好把勾的左侧起始线条截掉了一点，这样勾看起来就比较完美了
                }
                
            }
        }
    }

    @objc func doneButtonAction(){
        view.endEditing(true) //全局view点击关闭键盘
    }

}

extension ViewController{
    @objc func swipeToLeft(_ recognizer:UISwipeGestureRecognizer){
       print("swipeToLeft")
//线条向左回收
    }
}


extension ViewController:CAAnimationDelegate{
    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
//打勾动画结束，则显示主UI
//present一个UINavigationController
        showMainVC("0")
    }
    
    @objc func showMainVC(_ state:String){
        let mainVC = MainViewController()
        mainVC.title = "人生如逆旅我亦是行人"
        if let snapView = self.view.snapshot2View(){
            mainVC.superSnapshotView = snapView
            let position = ("0" == state) ? CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY) : CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY + 140.hFit)//以当前view的中心点做镜头动画扩展镜头的中心点
            mainVC.superSnapshotPosition = position
        }
        mainVC.didCloseBlock = { [weak self](snapshot) in
            if let snapImage = snapshot,let self = self{
                let tmpSnapView = UIImageView(frame: CGRect(x: 0, y: 0, width: screen_W, height: screen_H))
                tmpSnapView.image = snapImage
                self.view.addSubview(tmpSnapView)
                tmpSnapView.tag = 999 //关闭MainViewController时，将截屏临时添加到view上，然后在viewdidappear时，显示碎裂动画并将此view移除
            }
        }
        let naviVC = UINavigationController(rootViewController: mainVC)
        naviVC.modalPresentationStyle = .fullScreen
        self.present(naviVC, animated: false)
    }
}

extension ViewController: UITextFieldDelegate{
    func textFieldDidBeginEditing(_ textField: UITextField) {
        if 100 == textField.tag{
//用户名
            if showType != .PASS{//说明上一状态，不是在密码框内,说明是在本身，还是初始none状态，则不做操作
                showType = .USER
                return
            }
//从密码框切换到用户，则要进行动画，将遮住眼睛的手还原
            showType = .USER
            let rectLeftHand = self.imgLeftHand?.frame
            let rectRightHand = self.imgRightHand?.frame
            let offsetLeftW = 60.wFit
            let offsetLeftH = 35.wFit
            let rectLeftMask = self.imgLeftMaskHand?.frame
            let rectRightMask = self.imgRightMaskHand?.frame
            let maskHandW = 40.wFit
            UIView.animate(withDuration: 0.5, delay: 0, options: [.allowUserInteraction,.curveEaseInOut]) { [weak self] in
                if let self = self{
//遮眼睛的手放回原处
                    self.imgLeftHand!.frame = CGRect(x: rectLeftHand!.minX - offsetLeftW,
                                                     y: rectLeftHand!.minY + offsetLeftH,
                                                     width: rectLeftHand!.width,
                                                     height: rectLeftHand!.height)
//
                    self.imgRightHand!.frame = CGRect(x: rectRightHand!.minX + offsetLeftW - 2.wFit,
                                                     y: rectRightHand!.minY + offsetLeftH,
                                                     width: rectRightHand!.width,
                                                     height: rectRightHand!.height)
////
                    self.imgLeftMaskHand!.frame = CGRect(x: rectLeftMask!.minX - offsetLeftW,
                                                         y: rectLeftMask!.minY,
                                                         width: maskHandW, height: maskHandW)
//
                    self.imgRightMaskHand!.frame = CGRect(x: rectRightMask!.minX + offsetLeftW,
                                                          y: rectLeftMask!.minY,
                                                         width: maskHandW, height: maskHandW)
                }
            }
        }else if 101 == textField.tag{
//密码
            if showType == .PASS{//说明上一状态，不是在密码框内,说明是在本身，还是初始none状态，则不做操作
                return
            }
//从密码框切换到用户，则要进行动画，将遮住眼睛的手还原
            showType = .PASS
            let rectLeftHand = self.imgLeftHand?.frame
            let rectRightHand = self.imgRightHand?.frame
            let offsetLeftW = 60.wFit
            let offsetLeftH = 35.wFit
            let rectLeftMask = self.imgLeftMaskHand?.frame
            let rectRightMask = self.imgRightMaskHand?.frame
            //播放遮眼动画
            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 20, options: [.allowUserInteraction]) {
//usingSpringWithDamping: 设置弹性动画的阻尼(范围：0.0～1.0)，越接近0.0弹性越大，反之则越小。
//initialSpringVelocity: 表示一个初始速度，动画执行快慢由他和duration共同决定
                self.imgLeftHand!.frame = CGRect(x: rectLeftHand!.minX + offsetLeftW,
                                                 y: rectLeftHand!.minY - offsetLeftH,
                                                 width: rectLeftHand!.width,
                                                 height: rectLeftHand!.height)
                
                self.imgRightHand!.frame = CGRect(x: rectRightHand!.minX - offsetLeftW + 2.wFit,
                                                  y: rectRightHand!.minY - offsetLeftH,
                                                 width: rectLeftHand!.width,
                                                 height: rectLeftHand!.height)
                
                self.imgLeftMaskHand!.frame = CGRect(x: rectLeftMask!.minX + offsetLeftW,
                                                     y: rectLeftMask!.minY, width: 0, height: 0)
                
                self.imgRightMaskHand!.frame = CGRect(x: rectRightMask!.minX - offsetLeftW,
                                                     y: rectLeftMask!.minY, width: 0, height: 0)
            }
            
        }
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if 100 == textField.tag{
            if let passField = self.view.viewWithTag(101) as? UITextField{
                passField.becomeFirstResponder()
            }
        }else{
            textField.resignFirstResponder() //完成按钮关闭键盘
        }
        return true
    }
    
}

